package com.hxs.learn.shiro.realm;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import org.springframework.util.StringUtils;

import com.hxs.learn.entity.core.SysRole;
import com.hxs.learn.entity.core.SysRoleMenuPermission;
import com.hxs.learn.service.core.SysRoleMenuPermissionService;
import com.hxs.learn.service.core.SysRoleService;

/**
 * @author huxinsheng
 */
public abstract class BaseRealm extends AuthorizingRealm {

    private static final String OR_OPERATOR  = " or ";
    private static final String AND_OPERATOR = " and ";
    private static final String NOT_OPERATOR = "not ";

    public SimpleAuthorizationInfo initPermission(SysRoleService sysRoleService,
                                                  SysRoleMenuPermissionService roleMenuPermissionService,
                                                  String userId) {

        // 根据id查询用户的角色 和权限标识
        List<SysRole> roles       = sysRoleService.findByUserId(userId);
        Set<String>   roleSignSet = new HashSet<>();

        for (SysRole role : roles) {
            roleSignSet.add(role.getSign());
        }

        Set<String>                 permissionSet = new HashSet<>();
        List<SysRoleMenuPermission> permissions   = roleMenuPermissionService.findByUserId(userId);

        for (SysRoleMenuPermission permission : permissions) {
            String sign = permission.getSign();

            // 不为空
            if (StringUtils.hasLength(sign)) {
                permissionSet.add(sign);
            }
        }

        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

        info.addStringPermissions(permissionSet);
        info.addRoles(roleSignSet);

        return info;
    }

    /**
     * 支持or and not 关键词  不支持and or混用
     *
     * @param principals
     * @param permission
     * @return
     */
    @Override
    public boolean isPermitted(PrincipalCollection principals, String permission) {
        if (permission.contains(OR_OPERATOR)) {
            String[] permissions = permission.split(OR_OPERATOR);

            for (String orPermission : permissions) {
                if (isPermittedWithNotOperator(principals, orPermission)) {
                    return true;
                }
            }

            return false;
        } else if (permission.contains(AND_OPERATOR)) {
            String[] permissions = permission.split(AND_OPERATOR);

            for (String orPermission : permissions) {
                if (!isPermittedWithNotOperator(principals, orPermission)) {
                    return false;
                }
            }

            return true;
        } else {
            return isPermittedWithNotOperator(principals, permission);
        }
    }

    private boolean isPermittedWithNotOperator(PrincipalCollection principals, String permission) {
        if (permission.startsWith(NOT_OPERATOR)) {
            return !super.isPermitted(principals, permission.substring(NOT_OPERATOR.length()));
        } else {
            return super.isPermitted(principals, permission);
        }
    }
}


//~ Formatted by Jindent --- http://www.jindent.com
